fix(heights): repair native stature potion brewing
This commit is contained in:
@@ -43,6 +43,7 @@ public final class SpigotHeightsPlugin extends JavaPlugin {
|
||||
|
||||
potions = new PotionRecipes(this);
|
||||
potions.register();
|
||||
getServer().getPluginManager().registerEvents(new StatureBrewing(potions), this);
|
||||
getServer().getPluginManager().registerEvents(
|
||||
new StatureListener(potions, stature::drink, stature::resume,
|
||||
task -> getServer().getScheduler().runTask(this, task)), this);
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
package games.dmg.spigotheights;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.BrewEvent;
|
||||
|
||||
/** Completes authenticated stature conversions at the native brewing transaction boundary. */
|
||||
public final class StatureBrewing implements Listener {
|
||||
private final PotionRecipes potions;
|
||||
|
||||
public StatureBrewing(PotionRecipes potions) {
|
||||
this.potions = potions;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
|
||||
public void detachResults(BrewEvent event) {
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// Native no-op results can mirror the input itself. Detach before normal result modifiers
|
||||
// run, otherwise an in-place result edit also changes the inventory despite cancellation.
|
||||
for (int slot = 0; slot < Math.min(3, event.getResults().size()); slot++) {
|
||||
ItemStack input = event.getContents().getItem(slot);
|
||||
if (potions.identify(input) != null && input.equals(event.getResults().get(slot))) {
|
||||
event.getResults().set(slot, input.clone());
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException exception) {
|
||||
event.setCancelled(true);
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||
public void brew(BrewEvent event) {
|
||||
try {
|
||||
convert(event);
|
||||
} catch (RuntimeException exception) {
|
||||
// Paper logs listener exceptions and continues dispatch: cancel first to prevent item loss.
|
||||
event.setCancelled(true);
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
|
||||
private void convert(BrewEvent event) {
|
||||
ItemStack ingredient = event.getContents().getIngredient();
|
||||
if (event.isCancelled() || ingredient == null) {
|
||||
return;
|
||||
}
|
||||
Material source;
|
||||
Material target;
|
||||
if (ingredient.getType() == Material.GUNPOWDER) {
|
||||
source = Material.POTION;
|
||||
target = Material.SPLASH_POTION;
|
||||
} else if (ingredient.getType() == Material.DRAGON_BREATH) {
|
||||
source = Material.SPLASH_POTION;
|
||||
target = Material.LINGERING_POTION;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
for (int slot = 0; slot < 3; slot++) {
|
||||
ItemStack input = event.getContents().getItem(slot);
|
||||
StaturePotion kind = potions.identify(input);
|
||||
if (kind != null && input.getType() == source) {
|
||||
if (slot >= event.getResults().size() || input.getAmount() != 1) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
ItemStack result = event.getResults().get(slot);
|
||||
if (result != null && result.getType() == target
|
||||
&& result.getAmount() == 1 && potions.identify(result) == kind) {
|
||||
continue;
|
||||
}
|
||||
if (!input.equals(result)) {
|
||||
// Do not overwrite another plugin's output or spend ingredients on a failed conversion.
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
// 2618 recognizes custom recipes but mix() returns base-less potions unchanged.
|
||||
// Correct only that no-op; leave inventory and ingredient accounting to the server.
|
||||
event.getResults().set(slot, potions.create(kind, target));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user